package models.jsf.base;

import com.etfbl.net.dao.DAOBase;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.convert.Converter;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import models.jsf.util.JsfUtil;
import models.jsf.util.PaginationManager;
import javax.faces.event.AjaxBehaviorEvent;
/**
 *
 * @author abosancic
 * @date Apr-02-2013
 */ 

public class BaseController<T> implements Serializable {

    protected T selected;
    protected DataModel items = null;

    protected PaginationManager pagination;
    protected int paginationSize = 10;
    protected int selectedItemIndex;

    public BaseController() {
    }

    protected DAOBase getFacade() {
        return null;
    }
    
    protected Class<T> getClassType(){
        return null;
    }
    
    public T getSelected() {
        if (selected == null) {
            try {
                selected = (T) getClassType().newInstance();
            } catch (InstantiationException ex) {
                Logger.getLogger(BaseController.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(BaseController.class.getName()).log(Level.SEVERE, null, ex);
            }
            selectedItemIndex = -1;
        }
        return selected;
    }
    
    public PaginationManager getPagination() {
        if (pagination == null) {
            pagination = new PaginationManager(paginationSize) {
                @Override
                public int getItemsCount() {
                    return getFacade().countRows();
                }

                @Override
                public DataModel createPageDataModel() {
                    return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageSize()}));
                }
            };
        }
        return pagination;
    }

    public String prepareList() {
        items = null;
        return "List";
    }

    public String prepareView() {
        selected = (T) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        return "View";
    }

    public String prepareCreate() {
        try {
            selected = getClassType().newInstance();
        } catch (InstantiationException ex) {
            Logger.getLogger(BaseController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(BaseController.class.getName()).log(Level.SEVERE, null, ex);
        }
        selectedItemIndex = -1;
        return "Create";
    }

    public String create() {
       return null;
    }

    public String prepareEdit() {
        selected = (T) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        return "Edit";
    }

    public String destroy() {
        selected = (T) getItems().getRowData();
        selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
        performDestroy();
        recreatePagination();
        return prepareList();
    }

    public String destroyAndView() {
        performDestroy();
        items = null;
        updateCurrentItem();
        if (selectedItemIndex >= 0) {
            return "View";
        } else {
            return prepareList();
        }
    }

    protected void performDestroy() {
       
    }

    protected void updateCurrentItem() {
        int count = getFacade().countRows();
        if (selectedItemIndex >= count) {
            selectedItemIndex = count - 1;
            if (pagination.getPageFirstItem() >= count) {
                pagination.previousPage();
            }
        }
        if (selectedItemIndex >= 0) {
            selected = (T) getFacade().findRange(new int[]{selectedItemIndex, selectedItemIndex + 1}).get(0);
        }
    }

    public DataModel getItems() {
        if (items == null) {
            items = getPagination().createPageDataModel();
        }
        return items;
    }

    protected void recreatePagination() {
        pagination = null;
    }

    public String next() {
        getPagination().nextPage();
        return prepareList();
    }

    public String previous() {
        getPagination().previousPage();
        return prepareList();
    }

    public void nextAjax(AjaxBehaviorEvent event) {
        next();
    }
    
    public void previousAjax(AjaxBehaviorEvent event) {
        previous();
    }
    public SelectItem[] getItemsAvailableSelectMany() {
        return JsfUtil.getSelectItems(getFacade().findAll(), false);
    }

    public SelectItem[] getItemsAvailableSelectOne() {
        return JsfUtil.getSelectItems(getFacade().findAll(), true);
    }

    public abstract static class BaseControllerConverter implements Converter {

        protected java.lang.Integer getKey(String value) {
            java.lang.Integer key;
            key = Integer.valueOf(value);
            return key;
        }

        protected String getStringKey(java.lang.Integer value) {
            StringBuffer sb = new StringBuffer();
            sb.append(value);
            return sb.toString();
        }

    }
}
